home *** CD-ROM | disk | FTP | other *** search
- // Non-assembler matrix math routines
- // All code by Dave Stampe, last updated 23/12/93
-
- /*
- This code is part of the VR-386 project, created by Dave Stampe.
- VR-386 is a desendent of REND386, created by Dave Stampe and
- Bernie Roehl. Almost all the code has been rewritten by Dave
- Stampre for VR-386.
-
- Copyright (c) 1994 by Dave Stampe:
- May be freely used to write software for release into the public domain
- or for educational use; all commercial endeavours MUST contact Dave Stampe
- (dstampe@psych.toronto.edu) for permission to incorporate any part of
- this software or source code into their products! Usually there is no
- charge for under 50-100 items for low-cost or shareware products, and terms
- are reasonable. Any royalties are used for development, so equipment is
- often acceptable payment.
-
- ATTRIBUTION: If you use any part of this source code or the libraries
- in your projects, you must give attribution to VR-386 and Dave Stampe,
- and any other authors in your documentation, source code, and at startup
- of your program. Let's keep the freeware ball rolling!
-
- DEVELOPMENT: VR-386 is a effort to develop the process started by
- REND386, improving programmer access by rewriting the code and supplying
- a standard API. If you write improvements, add new functions rather
- than rewriting current functions. This will make it possible to
- include you improved code in the next API release. YOU can help advance
- VR-386. Comments on the API are welcome.
-
- CONTACT: dstampe@psych.toronto.edu
- */
-
-
- #include <mem.h> /* memcpy() */
-
- #include "intmath.h"
-
-
- /******************** MISC. VECTOR MATH ****************/
-
- /* replaces column N of a matrix with cross of other 2 */
- /* used to speed computations, repair matrix scaling */
-
- void cross_column(MATRIX m, int col)
- {
- extern void cross_product(long *col1, long *col2, long *col3); // asm code
-
- long *c1, *c2, *c3;
-
- switch (col)
- {
- case 0:
- c1 = &(m[0][1]);
- c2 = &(m[0][2]);
- c3 = &(m[0][0]);
- break;
-
- case 1:
- c1 = &(m[0][2]);
- c2 = &(m[0][0]);
- c3 = &(m[0][1]);
- break;
-
- case 2:
- c1 = &(m[0][0]);
- c2 = &(m[0][1]);
- c3 = &(m[0][2]);
- break;
- }
-
- cross_product(c1, c2, c3);
- }
-
-
- /****************** MATRIX MANIPULATION ***************/
-
-
- #define XFSC 536870912 /* 2**29 for shifting real to <3.29 fixed point */
-
- void identity_matrix(MATRIX m)
- {
- int i, j;
-
- m[0][0] = m[1][1] = m[2][2] = XFSC;
- m[1][0] = m[2][0] = m[3][0] = 0;
- m[0][1] = m[2][1] = m[3][1] = 0;
- m[0][2] = m[1][2] = m[3][2] = 0;
- }
-
- /* copy 3x4 matrix */
-
- void matrix_copy(MATRIX m, MATRIX n)
- {
- memcpy (n, m, sizeof(MATRIX));
- }
-
- /* copy 3x3 rotation part of matrix */
-
- void matrix_rot_copy(MATRIX m, MATRIX n)
- {
- memcpy (n, m, sizeof(MATRIX));
- n[3][0] = n[3][1] = n[3][2] = 0;
- }
-
-
-
- /*************** ANGLE/POSITION TO HOMOGENOUS MATRIX ************/
-
- // assembler from matrixm.asm
-
- extern void matrix_RXYZ(MATRIX m, long rx, long ry, long rz,
- long tx, long ty, long tz);
-
- extern void matrix_RYXZ(MATRIX m, long rx, long ry, long rz,
- long tx, long ty, long tz);
-
- extern void matrix_RXZY(MATRIX m, long rx, long ry, long rz,
- long tx, long ty, long tz);
-
-
- #define RXYZ 1 /* matrix rotation types */
- #define RYXZ 0
- #define RXZY 2
- #define RZYX 5
- #define RZXY 4
- #define RYZX 6 /* create rotation/translation */
- /* "matrix" from angle data */
-
-
- void multi_matrix(MATRIX m, long rx, long ry, long rz,
- long tx, long ty, long tz, int type )
- {
- if (rx == 0) /* tests for single-axis rotates */
- { /* much faster to directly make */
- if (ry == 0)
- {
- identity_matrix(m);
- if (rz != 0)
- {
- m[0][0] = m[1][1] = icosine(rz);
- m[1][0] = isine(rz);
- m[0][1] = -m[1][0];
- }
- goto shortcut;
- }
- else if (rz == 0)
- {
- identity_matrix(m);
- m[0][0] = m[2][2] = icosine(ry);
- m[0][2] = isine(ry);
- m[2][0] = -m[0][2];
- goto shortcut;
- }
- }
- else if (ry == 0 && rz == 0)
- {
- identity_matrix(m);
- m[1][1] = m[2][2] = icosine(rx);
- m[2][1] = isine(rx);
- m[1][2] = -m[2][1];
- goto shortcut;
- }
-
- switch(type&7)
- {
- case RXYZ:
- matrix_RXYZ(m,rx,ry,rz,tx,ty,tz);
- break;
-
- case RZYX:
- matrix_RXYZ(m,-rx,-ry,-rz,tx,ty,tz); // reverse order: just
- matrix_transpose(m,m); // negate angles, take
- break; // rotational inverse
-
- case RYXZ:
- matrix_RYXZ(m,rx,ry,rz,tx,ty,tz);
- break;
-
- case RZXY:
- matrix_RYXZ(m,-rx,-ry,-rz,tx,ty,tz);
- matrix_transpose(m,m);
- break;
-
- case RXZY:
- matrix_RXZY(m,rx,ry,rz,tx,ty,tz);
- break;
-
- case RYZX:
- matrix_RXZY(m,-rx,-ry,-rz,tx,ty,tz);
- matrix_transpose(m,m);
- break;
- }
- return;
-
- shortcut:
- m[3][0] = tx;
- m[3][1] = ty;
- m[3][2] = tz;
- }
-
- /* the default matrix: RYXZ */
- /* used for camera transform */
-
- void std_matrix(MATRIX m, long rx, long ry, long rz,
- long tx, long ty, long tz)
- {
- multi_matrix(m, rx, ry, rz, tx, ty, tz, RYXZ);
- }
-
-
- /*************** MATRIX-TO-ANGLES (RYXZ ONLY) *************/
-
-
- void matrix_to_angle(MATRIX m, long *rx, long *ry, long *rz)
- {
- long t,p,a;
- long c2;
-
- if (m[1][2] > 536334041 || m[1][2] < -536334041)
- {
- c2 = magnitude32(m[0][2],m[2][2],0); /* need accuracy for this one */
- if (c2 > 2000000)
- {
- p = arccosine(c2);
- if (m[1][2] < 0) p = -p;
- }
- else
- {
- t = (m[1][2] < 0) ? 90*65536L : -90*65536L; /* works with Z-axis rule */
- a = 0;
- p = arccosine(m[1][0]);
- if (m[1][2] > 0) p = -p;
-
- goto assign;
- }
- }
- else p = -arcsine(m[1][2]);
-
- t = arctan2(m[0][2], m[2][2]);
- a = arctan2(m[1][0], m[1][1]);
-
- assign:
-
- *ry = t;
- *rx = p;
- *rz = a;
- }
-
-
- /******************* MATRIX RENORMALIZE ***************/
-
-
- #define XFLC 536870912 // fixed -> <3.29>
-
- void renormalize_matrix(MATRIX m) /* slow but sure: do once every 1000 matrix mults */
- {
- set_vector_magnitude32(XFLC, &m[0][0], &m[0][1], &m[0][2]);
- set_vector_magnitude32(XFLC, &m[1][0], &m[1][1], &m[1][2]);
- set_vector_magnitude32(XFLC, &m[2][0], &m[2][1], &m[2][2]);
- set_vector_magnitude32(XFLC, &m[0][0], &m[1][0], &m[2][0]);
- set_vector_magnitude32(XFLC, &m[0][1], &m[1][1], &m[2][1]);
- set_vector_magnitude32(XFLC, &m[0][2], &m[1][2], &m[2][2]);
- }
-
-
- /******************* MATRIX FROM VECTOR ***************/
-
-
- void vector_to_matrix(MATRIX m, long x, long y, long z)
- {
- long ya = arctan2(x, z);
- long sz = magnitude32(x,y,z);
- long r = divide_29(y, sz );
- long xa = -arcsine(r);
-
- std_matrix(m, xa, ya, 0, 0, 0, 0);
- }
-
-